第 3 步 - 创建预设件实例并从文件系统加载图像

在本教程的这一步骤中,您将创建到Widget Item Prefab 预设件节点的引用。您将使用此预设件创建表示Widget Grid List Box 节点中小组件的预设件实例,并为每个小组件设置名称、图标和描述,以Widget Item Prefab 预设件实例填入 Widget Grid List Box

要创建预设件实例并从文件系统加载图像:

  1. 获得Widget Item Prefab 预设件。您将使用该预设件实例表示Widget Grid List Box 节点中的小组件,当用户选择小组件时使用该动画剪辑聚焦到选定的小组件。
    要访问 kzb 文件中的资源和节点,您可以使用资源 ID 或 kzb 文件 URL。使用资源 ID 访问资源是首选方式。访问资源时,您需要指定正在获取的资源类型。
    virtual void onProjectLoaded() KZ_OVERRIDE
    {
    ...        
        //获取小组件图标的可重复使用的预设件模板引用。
        ResourceManager* resourceManager = getDomain()->getResourceManager();
        PrefabTemplateSharedPtr widgetItemPrefabTemplate = resourceManager->acquireResource<PrefabTemplate>("kzb://programmer_tutorial/Prefabs/Widget Item Prefab");
    ...
    }
    
    Kanzi 中,资源为共享的,因此可以重复使用。多个对映射到相同资源 URL 的 acquireResource 调用都会返回相同资源。Kanzi 中的资源是以共享指针计数的引用。因为继续使用这些资源,将共享指针存储为成员变量。该应用程序被清除时,共享指针也被清除,并且 Kanzi 自动释放资源。
  2. ProgrammerTutorialApplication 类中,为 WidgetDescription 结构创建构造函数,它定义小组件名称、图标和描述,设置小组件数量,并定义小组件描述数组。
    class ProgrammerTutorialApplication : public ExampleApplication
    {
    private: 
        //包含小组件描述的结构。
        struct WidgetDescription
        {
            //构造函数。
            explicit WidgetDescription(const string& widgetName, const string& iconName, const string& description) : 
                    widgetName(widgetName),
                    iconName(iconName),
                    description(description)
            {
            }
    
            //小组件名称。
            string widgetName;
            //小组件图标文件的名称。
            string iconName;
            //描述面板中显示的小组件描述。
            string description;
        };
    
        //数组大小以及添加到该数组中的项数量
        //定义应用程序包含的小组件数量。
        typedef array<WidgetDescription, 14> WidgetDescriptionArray;
    
        //创建小组件描述数组。
        static const WidgetDescriptionArray widgetDescriptions;
    ...
    };
  3. ProgrammerTutorialApplication 类后,初始化 widgetDescriptions 数组,其中每个数组条目包含名称、图像文件名和小组件描述。
    //小组件描述数组初始化。
    const ProgrammerTutorialApplication::WidgetDescriptionArray ProgrammerTutorialApplication::widgetDescriptions =
    {
        WidgetDescription("Browser",      "Icon001.png", "Browser description"),
        WidgetDescription("Mail",         "Icon002.png", "Mail description"),
        WidgetDescription("Game",         "Icon003.png", "Game description"),
        WidgetDescription("Time",         "Icon004.png", "Time description"),
        WidgetDescription("Calculator",   "Icon005.png", "Calculator description"),
        WidgetDescription("Camera",       "Icon006.png", "Camera description"),
        WidgetDescription("Movie",        "Icon007.png", "Movie description"),
        WidgetDescription("Calendar",     "Icon008.png", "Calendar description"),
        WidgetDescription("Chat",         "Icon009.png", "Chat description"),
        WidgetDescription("Music",        "Icon010.png", "Music player description"),
        WidgetDescription("Ninja",        "Icon011.png", "Ninja description"),
        WidgetDescription("Splatter",     "Icon012.png", "Splatter description"),
        WidgetDescription("Superstar",    "Icon013.png", "Superstar description"),
        WidgetDescription("Chess",        "Icon014.png", "Chess description")
    };
    
  4. onProjectLoaded() 函数的 ProgrammerTutorialApplication 类中,存储获得的资源和节点(在 using std::swap; 后)并获得Widget Item Prefab 后,添加 for 循环,以使用Widget Item Prefab 预设件实例中的实例填入Widget Grid List Box 节点。注意,水平滚动是网格列表框 (Grid List Box) 节点的内置功能。
    virtual void onProjectLoaded() KZ_OVERRIDE
    {
    ...
        //填充小组件列表。
        for (WidgetDescriptionArray::const_iterator it = cbegin(widgetDescriptions), end = cend(widgetDescriptions); it != end; ++it)
            {
                //实例化Widget Item Prefab 预设件。
                Node3DSharedPtr widgetItem = widgetItemPrefabTemplate->instantiate<Node3D>(it->widgetName);
    
                //将Widget Item Prefab 预设件实例添加到Widget Grid List Box 节点。
                //Widget Grid List Box 拥有该实例。
                m_widgetList->addItem(widgetItem);
    
                //对第二行的所有小组件应用平移,使其呈
                //蜂窝形式排列。将这些小组件按三行排列。
                //当Widget Grid List Box 排列其项时,您可以
                //通过应用渲染变换,调整这些小组件的位置。
                if (distance(cbegin(widgetDescriptions), it) % 3 == 1)
                {
                    widgetItem->setRenderTransformation(SRTValue3D::createTranslation(Vector3(2.75f, 0.0f, 0.0f)));
                }
    
                //通过更改 IconTexture 资源 ID 指向
                //文件系统中的图像,应用该纹理。图像位于正在运行的应用程序
                //工作目录中。
                widgetItem->addResource(ResourceID("IconTexture"), "file://./"+ it->iconName);
     
                //使用您在本教程的上一步骤中访问的相同自定义属性
                //类型设置该小组件的名称和描述。
                //在 Kanzi Studio 中创建预设件时,Kanzi 会将要在预设件的每个实例中
                //自定义的节点,添加至
                //要编辑属性的预设件的根节点,并在节点中创建对这些属性的
                //绑定。
                widgetItem->setProperty(*m_widgetNamePropertyType, it->widgetName);
                widgetItem->setProperty(*m_widgetDescriptionPropertyType, it->description);
            }
    }
    运行应用程序时,您可以看到Widget Grid List Box 节点中已实例化和排列的Widget Item Prefab 预设件。Widget Grid List Box 节点中的每个小组件都有名称和图标,并且您可以水平滚动列表框。在本教程的下一步骤中,您将实现用户从 Widget Grid List Box 选择小组件时发生的事件。

< 上一步
下一步 >

另请参阅

使用预设件

从文件系统加载图像